//xlang Source, Name:RCPClient.xcsm
//Date: Sat Oct 23:19:50 2018

class RCPClient {
    public static const int TIMEOUT = 30000;
    RemoteCallPipe<IClient, IServer> rcs;
    Client client;
    String host;
    int port;
    int hreadtid = 0;
    bool needAlive = false;
    
    public RemoteCallPipe<IClient, IServer> getRemoteCallPipe() {
        return rcs;
    }
    
    
    class XAsyncOutput : AsyncOutput {
        StreamSocket _socket = nilptr;
        bool bExit = false;
        public bool create() {
            bool brest = false;
            synchronized (XAsyncOutput.this) {
                _socket = new StreamSocket();
                _socket.setSoTimeout(RCPClient.TIMEOUT / 2);
                try {
                    brest = _socket.connect(host, port, 5000);
                } catch(Exception e) {

                }
            }
            //_system_.consoleWrite("connect result:" + brest);
            return brest;
        }

        bool dataDeparture(AsyncInput input, long context, long bind, byte [] buffer, int offset, int length) {
            synchronized (XAsyncOutput.this) {
                if (_socket != nilptr) {
                    //_system_.consoleWrite("client tx" + length + "\n");
                    try{
                        return length == _socket.write(buffer, offset, length);
                    }catch(Exception e){
                        
                    }
                }
            }

            return false;
        }

        void deleteInstance(AsyncInput input, long context) {}

        long newInstance(AsyncInput input, String ip, int port, long bind) {
            return 0;
        }

        long getInstanceId(long context) {
            return 0;
        }

        long cloneContext(long context) {
            return 0;
        }

        void releaseContext(long context) {}

        void resetAlive(){
            needAlive = false;
            client.resetAlive();
        }
        
        public void do_loop() {
            byte [] buffer = new byte[8192];
            int rd = 0;
            
            
            while (!bExit) {
                StreamSocket socket = nilptr;
                
                synchronized (XAsyncOutput.this) {
                    socket = _socket;
                }
                
                bool berror = false;
                if (socket != nilptr) {
                    
                    if (needAlive){
                        needAlive = false;
                        rcs.onheart(0, hreadtid++);
                    }
                    
                    try {
                        while ((rd = socket.read(buffer, 0, 8192)) > 0) {
                            rcs.getAsyncDirectInput().dataArrives(XAsyncOutput.this, 0, buffer, 0, rd);
                            resetAlive();
                        }
                        berror = rd <= 0;
                    }catch(TimeoutException t){ //超时
                        needAlive = true;
                        if (client.isAlive() == false){
                            berror = true;
                        }
                    }catch(Exception e) {   //发生错误
                        berror = true;
                    }
                    
                    if (berror){
                        socket.close();
                        synchronized (XAsyncOutput.this) {
                            _socket = nilptr;
                        }
                        
                        try{
                        	Thread.sleep(5000);// 5秒后重连
                        }catch(Exception e){
                        	
                        }
                    }
                    
                } else 
                if (create()){
                    resetAlive();
                    try {
                        startInThread();
                    } catch(Exception e) {

                    }
                }
                
            }
        }
        
        bool bstarting = false;
        
        public void startInThread() {
            synchronized (RCPClient.this) {
                if (bstarting){
                    return;
                }
                bstarting = true;
                new Thread() {
                    void run()override {
                        bExit = !restart();
                        synchronized (RCPClient.this) {
                            bstarting = false;
                        }
                    }
                } .start();
            }
        }
    };

    XAsyncOutput ao = new XAsyncOutput();

    IRCPEventHandler rcph = new IRCPEventHandler() {
        bool onNewInstance(long context, int type)override {
            return true;
        }
        bool onDeleteInstance(long context)override {
            return true;
        }
        void onAccessFailed(long context)override {
        }
        bool onTimeout(long context)override {
            return true;
        }
    };



    public bool restart() {
        rcs = new RemoteCallPipe<IClient, IServer>();
        if (rcs.create(ao, rcph, client, false)) {
            rcs.enableBuffer(true);
            //开启远程调用通道, 超时5000毫秒
            if (0 == rcs.startForClient(0, 5000)){
                //_system_.consoleWrite("RCP SUCCESS\n");
                if (rcs.login(0,BusinessClt.getKey()) == false){
                    Service.Log.e(Service.ServiceName,"invalid key!");
                }
                return true;
            }else{
                //_system_.consoleWrite("RCP FAILED\n");
            }
        }
        return false;
    }

    public bool create(Client _client, String _host, int _port) {
        //异步输出接口
        client = _client;
        host = _host;
        port = _port;
        ao.do_loop();
        return true;
    }
};